<template>
  <span>
    <el-upload
      v-if="!inputDisabled"
      :style="uploadStyle"
      action=""
      :class="['ac-file', {'is-disabled': inputDisabled}]"
      :disabled="inputDisabled"
      :multiple=false
      :http-request="handleUpload"
      :file-list="fileList"
      :show-file-list=false
      :before-upload="handleBeforeUpload"
    >
      <el-button
        v-if="inputDisabled !== true"
        style="margin-right: 10px;"
        type="success"
      >
        <ac-icon
          iconId="018ece4f70fcf0627f81"
          style="margin-right: 5px"
        />点击上传
      </el-button>
    </el-upload>

    <el-image-viewer
      v-if="showViewer"
      :z-index="9999"
      teleported
      @close="closeViewer"
      :url-list="imageUrls"
      hide-on-click-modal
    />

    <span v-for="(item, index) in fileList" class="file" :key="index">
      <span class="file-item" :class="[{'is-disabled': inputDisabled}]">
        <span class="file-name" :title="item.name">
          <span
            style="cursor: pointer"
            v-if="isKnowFile(item)"
          >
            <span @click="showFile(item)">
              {{item.name}}
            </span>
          </span>
          <span
            style="cursor: pointer"
            v-else-if="item.name.toLowerCase().endsWith('.png')
              || item.name.toLowerCase().endsWith('.jpeg')
              || item.name.toLowerCase().endsWith('.jpg')
              || item.name.toLowerCase().endsWith('.bmp')
              || item.name.toLowerCase().endsWith('.gif')"
          >
            <span @click="showImage(item)">
              {{item.name}}
            </span>
          </span>
          <span v-else><span>{{item.name}}</span></span>
        </span>
        <ac-icon
          v-if="!inputDisabled && item.status === 1"
          size="20"
          color="#999"
          iconId="018dcab3d3dfd6e82393"
          class="spinner"
          title="上传中..."
        />
        <ac-icon
          v-if="inputDisabled || (!inputDisabled && item.status === 2)"
          size="20"
          color="#999"
          iconId="018dc9c3efed1f464d38"
          title="下载"
          @click="downloadFile(item)"
        />
        <ac-icon
          v-if="!inputDisabled && item.status === 2"
          size="20"
          color="#999"
          iconId="018dc9c3efd3a0502886"
          title="删除"
          @click="deleteFile(item)"
        ></ac-icon>
      </span>
    </span>
  </span>

  <el-dialog
    :title="dialogTitle"
    v-model="dialogVisible"
    class="no-padding"
    append-to-body
    destroy-on-close
    draggable
    fullscreen
  >
    <vue-office-docx v-if="dialogFileType === 'docx'" :src="dialogUrl" />
    <vue-office-excel v-if="dialogFileType === 'excel'" :src="dialogUrl" />
  </el-dialog>
</template>

<script setup>
import { onMounted, ref, watch } from 'vue';
import api from '@/http/api';
import { ElMessage, ElMessageBox, useDisabled } from 'element-plus';
import VueOfficeExcel from "@vue-office/excel";
import VueOfficeDocx from "@vue-office/docx";
import loading from "@/utils/loading";

const emit = defineEmits(['update:modelValue', 'change']);
const props = defineProps({
  modelValue: String,
  uploadStyle: {
    type: String,
    default: ''
  },
});

const uploadCnt = ref(0);
const fileId = ref('');
const fileList = ref([]);
const baseUrl = ref(import.meta.env.VITE_API_PATH);
const showViewer = ref(false);
const imageUrls = ref([]);
const inputDisabled = useDisabled();

const dialogTitle = ref('');
const dialogVisible = ref(false);
const dialogFileType = ref('');
const dialogUrl = ref('');

const showImage = (file) => {
  imageUrls.value = [];
  if (file && file.id) {
    imageUrls.value = [baseUrl.value + '/file/image/' + file.id];
    showViewer.value = true;
  }
};

const closeViewer = () => {
  showViewer.value = false;
};

const handleUpload = (file) => {
  return new Promise((resolve, reject) => {
    api.upload({'file': file.file, type: file.file.type}).then((res) => {
      uploadCnt.value--;

      const filters = fileList.value.filter(item => item.name === res.data.trueName && item.status === 1);
      if (filters.length > 0) {
        filters[0].id = res.data.id;
        filters[0].status = 2;
      }

      fileList.value = Object.assign([], fileList.value.filter(item => item.name === res.data.trueName));
      emit('change', fileList.value[0]);
      emit('update:modelValue', fileList.value[0].id);
      resolve();
    }).catch(() => {
      uploadCnt.value--;
      reject();
    });
  })
};

const handleBeforeUpload = (file) => {
  const isLt100M = file.size / 1024 / 1024 < 100;
  if (!isLt100M) {
    ElMessage.error("上传大小不能超过 100MB!");
  } else {
    fileList.value = Object.assign([], [{name: file.name, status: 1}]);
    uploadCnt.value++;
  }

  return isLt100M;
};

const downloadFile = (file) => {
  api.downloadFileLocal(file.id);
};

const deleteFile = (file) => {
  ElMessageBox.confirm('请确认是否删除此文件【' + file.name + '】？', '提示', {type: 'warning'}).then(() => {
    api.deleteAffix(file.id).then(() => {
      fileList.value = fileList.value.filter(item => item.id !== file.id);
      if(fileList.value.length === 0) {
        fileId.value = '';
        emit('update:modelValue', fileId.value);
      }
    });
  }).catch(()=>{});
};

const loadData = () => {
  fileList.value = [];
  if (typeof props.modelValue !== "undefined" && props.modelValue != null && props.modelValue !== '') {
    api.queryFile(props.modelValue).then((res) => {
      if(res.data) {
        fileId.value = res.data.id;
        fileList.value = [{name: res.data.trueName, id: res.data.id, status: 2}];
      } else {
        fileId.value = '';
      }
    }).catch((res) => {
      ElMessage.error(res.message);
    });
  } else {
    fileId.value = '';
  }
};

const isKnowFile = (file) => {
  return file.name.toLowerCase().endsWith('.pdf')
    || file.name.toLowerCase().endsWith('.ofd')

    || file.name.toLowerCase().endsWith('.doc')
    || file.name.toLowerCase().endsWith('.docx')
    || file.name.toLowerCase().endsWith('.wps')

    || file.name.toLowerCase().endsWith('.ppt')
    || file.name.toLowerCase().endsWith('.pptx')

    || file.name.toLowerCase().endsWith('.xls')
    || file.name.toLowerCase().endsWith('.xlsx')
    || file.name.toLowerCase().endsWith('.et')
};

const showFile = (file) => {
  dialogUrl.value = '';
  if (file.name.toLowerCase().endsWith('.pdf')) {
    loading.showLoading("文件加载中，请稍候...");
    api.download(file.id).then((res) => {
      const blob = new Blob([res.data], {type: 'application/pdf'})
      const href = window.URL.createObjectURL(blob);
      window.open(href, '_blank');
      loading.hideLoading();
    }).catch((res) => {
      ElMessage.error(res.message);
      loading.hideLoading();
    });
  } else if (file.name.toLowerCase().endsWith('.docx')) {
    dialogTitle.value = "文件查看【" + file.name + "】"
    dialogUrl.value = baseUrl.value + '/file/file/' + file.id;
    dialogFileType.value = "docx";
    dialogVisible.value = true;
  } else if (file.name.toLowerCase().endsWith('.xlsx')) {
    dialogTitle.value = "文件查看【" + file.name + "】"
    dialogUrl.value = baseUrl.value + '/file/file/' + file.id;
    dialogFileType.value = "excel";
    dialogVisible.value = true;
  }
};

watch(() => props.modelValue, (newVal) => {
  if (newVal === undefined || newVal == null || newVal === ''
      || fileId.value == null || fileId.value === ''
      || newVal !== fileId.value) {
    loadData();
  }
});

onMounted(() => {
  loadData();
});
</script>

<style scoped lang="scss">
.file {
  width: 100%;
}
.file-item {
  width: 100%;
  display: flex;
  flex-direction: row;
  align-items: center;
  > span {
    margin-right: 5px;
  }
  :deep(.ac-icon) {
    cursor: pointer;
  }
}
.file-name {
  overflow: hidden;
  min-width: 0;
}
.file-name > span > span {
  align-items: center;
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
}
.file-upload {
  font-size: 18px;
  margin-left: 5px;
}
.file-download, .file-delete {
  font-size: 18px;
  cursor: pointer;
  margin-left: 5px;
  width: 25px;
}
.file-download:hover, .file-delete:hover {
  color: #409EFF;
}
.file-item[class~=is-disabled] .file-delete {
  display: none;
}
</style>
